package cn.iocoder.yudao.framework.web.servlet;

import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import jakarta.annotation.Nonnull;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.UUID;

import static cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler.HEADER_TRACE_ID;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * MDC (Mapped Diagnostic Context) 映射的诊断上下文
 *  <a href="https://mp.weixin.qq.com/s/58AowEyTTTgx5D6pO4FVBA">如何使用 SLF4J 的 MDC, 实现全链路追踪？</a>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/02/26
 */
public class MdcTraceIdFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, @Nonnull HttpServletResponse response, @Nonnull FilterChain filterChain) throws ServletException, IOException {
        String traceId = request.getHeader(HEADER_TRACE_ID);
        if (traceId == null || traceId.isEmpty()) {
            traceId = UUID.randomUUID().toString();
        }
        TracerUtils.putTraceId(traceId);
        try {
            response.setHeader(HEADER_TRACE_ID, traceId);
            filterChain.doFilter(request, response);
        } finally {
            TracerUtils.removeTraceId();
        }
    }

}